#include "page_weather.h"

namespace Page
{
    Weather::Weather() : Base(){};

    void Weather::show(Api::Data data)
    {
        Base::display.firstPage();
        do
        {
            // _displayTempCenter(85.23, 24, 100, 240);
            // Base::display.drawLine(100, 190, 100, 290, GxEPD_BLACK);
            // Base::display.drawLine(50, 240, 150, 240, GxEPD_BLACK);
            // Base::display.drawLine(50, 224, 150, 224, GxEPD_RED);
            _drawBoardToday(data);
            _drawBoardHours(data);
            _drawBoardDays(data);
        } while (Base::display.nextPage());
    }

    void Weather::_drawBoardToday(Api::Data data)
    {
        Base::display.drawRoundRect(layoutBoardTodayX, layoutBoardTodayY, layoutBoardTodayWidth, layoutScreenHeight, layputBoardRound, GxEPD_BLACK);
        Api::TodayData _todayData = data.getTodayData();
        Api::HardwareData _hardwareData = data.getHardwareData();

        // draw date
        uint16_t y_time = 30;
        _displayTextCenter(_todayData.getStrDay(), 18, layoutBoardTodayCenterX, y_time);

        // draw icon
        uint16_t y_wi = y_time + 42 + 64;
        _displayIconCenter(_todayData.getWeatherIcon(), 128, layoutBoardTodayCenterX, y_wi);

        // draw name
        uint16_t y_wn = y_wi + 64 + layoutBoardMargin + 14;
        _displayTextCenter(_todayData.getWeatherName(), 24, layoutBoardTodayCenterX, y_wn);

        // Area : Details( icon + text)
        // Notice: icon in center,   text margin left
        int _gridRowStep = 35;
        int _gridRow1Y = y_wn + 75,
            _gridRow2Y = _gridRow1Y + _gridRowStep,
            _gridRow3Y = _gridRow2Y + _gridRowStep,
            _gridRow4Y = _gridRow3Y + _gridRowStep;
        int _gridCol1XIcon = 39, _gridCol2XIcon = 125;
        int _gridCol1XText = 54, _gridCol2XText = 140;

        _displayIconCenter("temp", 24, _gridCol1XIcon, _gridRow1Y);
        _displayTempLeft(_todayData.getTemp(), 14, _gridCol1XText, _gridRow1Y);

        _displayIconCenter("humi", 24, _gridCol2XIcon, _gridRow1Y);
        _displayIntLeft(_todayData.getHumidity(), "%d%%", 14, _gridCol2XText, _gridRow1Y);

        _displayIconCenter("home_temp", 24, _gridCol1XIcon, _gridRow2Y);
        _displayTempLeft(_hardwareData.getTemperature(), 14, _gridCol1XText, _gridRow2Y);

        _displayIconCenter("home_humi", 24, _gridCol2XIcon, _gridRow2Y);
        _displayIntLeft(_hardwareData.getHumidity(), "%d%%", 14, _gridCol2XText, _gridRow2Y);

        _displayIconCenter("wind", 24, _gridCol1XIcon, _gridRow3Y);
        _displayIntLeft(_todayData.getWindSpeed(), "%dm/h", 14, _gridCol1XText, _gridRow3Y);


        _displayIconCenter("press", 24, _gridCol1XIcon, _gridRow4Y);
        _displayIntLeft(_todayData.getPressure(), "%dhPa", 14, _gridCol1XText, _gridRow4Y);

        float batteryPercent = data.getHardwareData().getBatteryPercent();
        Base::_displayBatteryCenter(batteryPercent, layoutBoardTodayCenterX, _gridRow4Y + 40);
    }

    void Weather::_drawBoardHours(Api::Data data)
    {
        Base::display.drawRoundRect(layoutBoardHourX, layoutBoardHourY, layoutBoardHourWidth, layoutBoardHourHeight, layputBoardRound, GxEPD_BLACK);
        std::vector<Api::HourData> hoursData = data.getHoursData();
        // docHours has 48h，we only need 24h skip by 2
        Serial2.printf("\n size of hoursData: %d\n", hoursData.size());

        // get max,min temp
        // temp bar height = (cuttentTemp - minTemp) * step + minTemp;
        // temp bar Y = tempDescent - height;
        float maxTemp = 0.0;
        float minTemp = 1000.0;
        for (int i = 0; i < 12; i++)
        {
            int _idx = i * 2;
            float _temp = hoursData[_idx].getTemp();
            if (_temp > maxTemp)
            {
                maxTemp = _temp;
            }
            if (_temp < minTemp)
            {
                minTemp = _temp;
            }
        }

        float _layoutHourTempStep = (layoutBoardHourTempBarHeightMax - layoutBoardHourTempBarHeightMin) / (maxTemp - minTemp);

        for (int i = 0; i < 12; i++)
        {
            int _idx = i * 2;
            Api::HourData _hourData = hoursData[_idx];

            // cal hour area x,y,with,height
            int _layoutBoardBeginX = layoutBoardHourX + layoutBoardMargin;
            int _layoutHourWidth = (layoutBoardHourWidth - layoutBoardMargin * 2) / 12;
            int _layoutHourBeginX = _layoutBoardBeginX + (i * _layoutHourWidth);
            int _layoutHourCenterX = _layoutHourBeginX + _layoutHourWidth / 2;

            float temp = _hourData.getTemp();

            // draw temp bar
            int _tempHeight = (temp - minTemp) * _layoutHourTempStep + layoutBoardHourTempBarHeightMin;
            // Serial2.printf("height: %d \n", _tempHeight);
            int _tempX = _layoutHourCenterX - (layoutBoardHourTempBarWidth / 2);
            int _tempY = layoutBoardHourTempBarDescent - _tempHeight;
            Base::display.fillRoundRect(_tempX, _tempY, layoutBoardHourTempBarWidth, _tempHeight, layoutBoardHourTempBarWidth, GxEPD_BLACK);

            // draw temp °
            _displayTempCenter(temp, 10, _layoutHourCenterX, _tempY - 15);

            // draw icon
            int _popPercent = _hourData.getPopPercent();
            if (_popPercent == 0)
            {
                // no rain
                _displayIconCenter(_hourData.getWeatherIcon(), 24, _layoutHourCenterX, layoutBoardHourTempBarDescent + 30);
            }
            else
            {
                // will rain
                _displayIconCenter(_hourData.getWeatherIcon(), 24, _layoutHourCenterX, layoutBoardHourTempBarDescent + 23);
                // String _strPopPercent = Helper::to_string(_popPercent) + "%";
                String _strPopPercent = String(_popPercent);
                // TODO: bad memory
                _strPopPercent.concat("%");
                _displayTextCenter(_strPopPercent.c_str(), 8, _layoutHourCenterX, layoutBoardHourTempBarDescent + 46);
            }

            // draw label time
            String _strTime = _hourData.getStrHour();
            _displayTextCenter(_strTime, 10, _layoutHourCenterX, layoutBoardHourTempBarDescent + 65);
        }
    }

    void Weather::_drawBoardDays(Api::Data data)
    {
        Base::display.drawRoundRect(layoutBoardDayX, layoutBoardDayY, layoutBoardDayWidth, layoutBoardDayHeight, layputBoardRound, GxEPD_BLACK);
        std::vector<Api::DayData> daysData = data.getDaysData();
        // docHours has 48h，we only need 24h skip by 2
        Serial2.printf("\n size of daysData: %d\n", daysData.size());

        // _displayTextCenter("CENTER", 14, layoutBoardDayX, layoutBoardDayY);

        // get max,min temp
        // temp bar height = (cuttentTemp - minTemp) * step + minTemp;
        // temp bar Y = tempDescent - height;
        float maxTemp = 0.0;
        float minTemp = 1000.0;
        for (int i = 0; i < 7; i++)
        {
            float _tempMax = daysData[i].getTempMax();
            float _tempMin = daysData[i].getTempMin();
            if (_tempMax > maxTemp)
            {
                maxTemp = _tempMax;
            }
            if (_tempMin < minTemp)
            {
                minTemp = _tempMin;
            }
        }

        float _innerTempStep = innerBDayTempBarWidth / (maxTemp - minTemp);

        for (int i = 0; i < 7; i++)
        {
            int innerRowCentY = innerDayRowBeginY + innerDayRowStepY * i + innerDayRowStepCenterY;
            Api::DayData _dayData = daysData[i];

            // day
            if (i == 0)
            {
                _displayTextCenter("Today", 12, innerBDayStrDayCX, innerRowCentY);
            }
            else
            {
                _displayTextCenter(_dayData.getStrWeek(), 12, innerBDayStrDayCX, innerRowCentY);
            }

            // icons
            _displayIconCenter(_dayData.getWeatherIcon(), 24, innerBDayIconCX, innerRowCentY);

            // temp bar
            float _dayTempMax = _dayData.getTempMax();
            float _dayTempMin = _dayData.getTempMin();
            int _tempX = innerBDayTempBarBeginX + (maxTemp - _dayTempMax) * _innerTempStep;
            int _tempWidth = (_dayTempMax - _dayTempMin) * _innerTempStep;
            Base::display.drawRoundRect(_tempX, innerRowCentY - 3, _tempWidth, innerBDayTempBarWide, innerBDayTempBarWide, GxEPD_BLACK);
            // temp max
            _displayTempCenter(_dayTempMax, 10, _tempX - 20, innerRowCentY);
            // temp max
            _displayTempCenter(_dayTempMin, 10, _tempX + _tempWidth + 20, innerRowCentY);
        }
    };

}